package siclink;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import javax.swing.JOptionPane;

public class PassTwo {

	public static int controlSectionAddress = 0x00;
	private static boolean hasControlSectionAddressBeenSet = false;
	private static String controlSectionName;
	private static int controlSectionLength;
	private static int startingAddress = 0x00;
	private static int startingAddressToModify = 0x00;
	private static int lengthOfMemoryToModify = 0x00;
	public static char[] memoryRegister =  new char[0x400];
	private static String FILE_READER_ERROR = "File Reader Error";
	private static String FILE_NOT_FOUND_ERROR_PART_1 = "File ";
	private static String FILE_NOT_FOUND_ERROR_PART_2 = " not found";

	public static void processFile(String source, int programAddress) throws Exception {
		if (!hasControlSectionAddressBeenSet) {
			controlSectionAddress = programAddress;
			hasControlSectionAddressBeenSet = true;
		}
		
		if (memoryRegister[0] == '\u0000') {
			Arrays.fill(memoryRegister, ".".charAt(0));	
		}
		FileReader fileReader = readSourceFile(source);
		BufferedReader buffer = new BufferedReader(fileReader);
		String line;
		try		{
			while((line = buffer.readLine()) != null){
				if(line.equals("")) continue;
				if (line.startsWith("H")){
					controlSectionName = line.substring(1,6).trim();
					controlSectionLength = SicLink.controlSectionTable.get(controlSectionName);
				}				
				if (line.startsWith("T")){
					startingAddress = (Integer.parseInt(line.substring(1, 7), 16) + controlSectionAddress) * 0x02;
					String objectCodes = line.substring(9);
					loadMemory(startingAddress, objectCodes);
				}
				if (line.startsWith("M")){
					startingAddressToModify = (Integer.parseInt(line.substring(1, 7), 16) + controlSectionAddress) * 0x02;
					//lengthOfMemoryToModify = Integer.parseInt(line.substring(7, 9), 16);
					lengthOfMemoryToModify = 0x06;
					String operator = line.substring(9, 10);
					String externalSymbol = line.substring(10).trim();
					modifyMemory(startingAddressToModify, lengthOfMemoryToModify, operator, externalSymbol);
				}				
				if (line.startsWith("E")){
					controlSectionAddress = controlSectionAddress + controlSectionLength;
				}				
			}
		}
		catch (IOException e) 		{
			showErrorMessage(FILE_READER_ERROR);
		}
	}

	private static void modifyMemory(int address,
			int length, String operator, String externalSymbol) {
		String addressString = "";
		String newAddressString = "";
		int newAddress = 0x00;
		for (int i = address; i < address + length;) {
			addressString = addressString + String.valueOf(memoryRegister[i]);
			i += 0x01;
		}
		if (operator.equalsIgnoreCase("+")) {
			newAddress = Integer.parseInt(addressString, 16) + SicLink.symbolTable.get(externalSymbol);
		} else if (operator.equalsIgnoreCase("-")) {
			newAddress = Integer.parseInt(addressString, 16) - SicLink.symbolTable.get(externalSymbol);
		}
		newAddressString = SicLink.pad(Integer.toHexString(newAddress).toUpperCase(), length);
		loadMemory(address, newAddressString);
	}

	private static void loadMemory(int startingAddress, String objectCodes) {
		int j = 0;
		String tempString = Integer.toHexString(objectCodes.length());
		for (int i = startingAddress; i < (startingAddress + Integer.parseInt(tempString, 16)); i++){
			memoryRegister[i] = objectCodes.charAt(j);
			j++;
		}
	}

	private static FileReader readSourceFile(String source) throws Exception	{
		try {
			return new FileReader(source);
		}
		catch (FileNotFoundException e){
			showErrorMessage(FILE_NOT_FOUND_ERROR_PART_1 + source + FILE_NOT_FOUND_ERROR_PART_2);
			return null;
		}
	}	

	private static void showErrorMessage(String message) throws Exception{
		JOptionPane.showMessageDialog(null, message, "Error!",
				JOptionPane.ERROR_MESSAGE);
		System.exit(1);
	}
}